package baidu.interceptor;

import common.spring.redis.RedisUnits;
import common.spring.redis.StringRedisUnits;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by asus on 2018/12/21.
 */
public class HttpInterceptor implements HandlerInterceptor {
    @Value("#{config['server.md5.nonce']}")
    private Long SIGN_EXPIRED_TIME;


    private static final String SIGN_KEY = "sign";

    private static final String TIMESTAMP_KEY = "timestamp";

    private static final String NONCE = "nonce";

    private static final String ACCESS_KEY = "accessKey";

    private static final String ACCESS_SECRET = "accessSecret";

    private static final String TOKEN="token";
    private static Map<String, String> map = new ConcurrentHashMap<String, String>();

    private final static Logger logger = LoggerFactory.getLogger(HttpInterceptor.class);

    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        Map map = this.parseRequestParamMap(httpServletRequest);
        String accessKey = httpServletRequest.getParameter(ACCESS_KEY);
        String accessSecret = httpServletRequest.getParameter(ACCESS_KEY);
//        if(map.size()==0){
//            return false;
//        }
//        if(!map.containsKey(TIMESTAMP_KEY)){
//            return false;
//        }
//        if(!map.containsKey(NONCE)){
//            return false;
//        }
//        if(!map.containsKey(SIGN_KEY)){
//            return false;
//        }
//        Long now = System.currentTimeMillis();
//        Long timestamp= NumberUtils.toLong(map.get(TIMESTAMP_KEY).toString());
        //检验时间戳
//        if(now-timestamp>SIGN_EXPIRED_TIME){
//            httpServletResponse.sendRedirect(httpServletRequest.getContextPath() + "/message/error?message=" + "无效时间戳");
//            return false;
//        }
//        String nonce=map.get(NONCE).toString();
//        String val = redisUnits.getString(nonce);
//        if(val!=null){
//            httpServletResponse.sendRedirect(httpServletRequest.getContextPath() + "/message/error?message=" + "nonce已存在");
//            return false;
//        }
//        redisUnits.setStringDay(nonce,nonce,1);
//        String token=map.get(TOKEN).toString();
//        String tokenVal=redisUnits.getString(token);
//        if(tokenVal==null){
//            httpServletResponse.sendRedirect(httpServletRequest.getContextPath() + "/message/error?message=" + "无效的token");
//            return false;
//        }
        if (!verificationSign(httpServletRequest, accessKey, accessSecret)) {
            httpServletResponse.sendRedirect(httpServletRequest.getContextPath() + "/message/error?message=" + "签名错误");
            return false;
        }
        return true;
    }

    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }

    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }

    final protected Map<String, Object> parseRequestParamMap(HttpServletRequest request) {
        Enumeration<String> argEnu = request.getParameterNames();
        Map<String, Object> args = new HashMap();
        while (argEnu.hasMoreElements()) {
            String argName = argEnu.nextElement();
            String[] value = request.getParameterValues(argName);
            if (value == null) {
                continue;
            }
            for (String v : value) {
                args.put(argName, v);
            }
            if (value.length > 1) {
                args.put(argName, value);
            }
        }
        return args;
    }

    private boolean verificationSign(HttpServletRequest request, String accessKey, String accessSecret) throws UnsupportedEncodingException {
        Enumeration<?> pNames = request.getParameterNames();
        Map<String, Object> params = new HashMap<String, Object>();
        while (pNames.hasMoreElements()) {
            String pName = (String) pNames.nextElement();
            if (SIGN_KEY.equals(pName)) continue;
            Object pValue = request.getParameter(pName);
            params.put(pName, pValue);
        }
        String originSign = request.getParameter(SIGN_KEY);
        String sign = createSign(params, accessSecret);
        return sign.equals(originSign);
    }
    private String createSign(Map<String, Object> params, String accessSecret)  {
        Set<String> keysSet = params.keySet();
        Object[] keys = keysSet.toArray();
        Arrays.sort(keys);
        StringBuilder temp = new StringBuilder();
        boolean first = true;
        for (Object key : keys) {
            if (first) {
                first = false;
            } else {
                temp.append("&");
            }
            temp.append(key).append("=");
            Object value = params.get(key);
            String valueString = "";
            if (null != value) {
                valueString = String.valueOf(value);
            }
            temp.append(valueString);
        }
        temp.append("&").append(ACCESS_SECRET).append("=").append("secret");
        return MD5(temp.toString());
    }
    public static String MD5(String data) {
        String encodeStr= DigestUtils.md5Hex(data);
        return encodeStr.toUpperCase();
    }

    public static  void main(String[] sta){
       String  stringA="AccessKey=access&home=world&name=hello&work=java&timestamp=now&nonce=random";
      String  stringSignTemp="AccessKey=access&home=world&name=hello&work=java&timestamp=now&nonce=random&SecretKey=secret";

       System.out.println(MD5(stringSignTemp));
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
         for (int i=0;i<3;i++){
             try {
                 System.out.println(simpleDateFormat.format(new Date())+":   "+System.currentTimeMillis());
                 Thread.sleep(10000 );
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }

        }

    }
}
